package casbinService

import (
	"errors"
	"fmt"
	"github.com/Sir-yuChen/funAnalyse/global"
	"github.com/Sir-yuChen/funAnalyse/model"
	"github.com/Sir-yuChen/funAnalyse/model/common/ApiReturn"
	"github.com/Sir-yuChen/funAnalyse/model/request"
	"github.com/Sir-yuChen/funAnalyse/utils"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"strings"
	"time"
)

type StockCasbinRoleRelationUserService struct{}

func NewStockCasbinRoleRelationUserService() *StockCasbinRoleRelationUserService {
	return &StockCasbinRoleRelationUserService{}
}

// AssigningRole 角色分配
func (u *StockCasbinRoleRelationUserService) AssigningRole(r *request.AssigningRoleRequest, c *gin.Context) (a ApiReturn.ApiReturnCode) {
	/*	角色分配 满足条件
		1. 校验两个用户的账户类型
		2. 主用户必须拥有需要分配的所有角色，【简单来说，就是要分配A,B角色，当前主用户，操作分配动作的账户，必须拥有A，B两个角色】
		3. 待分配的角色必须正常且存在状态
	*/
	customerId, _ := c.Get("customerId")
	//apiReturnCode := u.RelationshipJudgment(r.UserId, c)
	//操作用户是否是分配账户的上级 如新用户需要先分配部门
	//if apiReturnCode.Code != ApiReturn.OK.Code {
	//	return apiReturnCode
	//}
	var roleIds []string
	//1. 校验操作账户是否有当前角色分配给另一个账户
	sql := `select role_id from stock_casbin_role_relation_user where user_id = '` + fmt.Sprint(customerId) + `' And role_id in (` + r.RoleIds + `)`
	err := global.GVA_DB.Raw(sql).Scan(&roleIds).Error
	if err != nil {
		global.GVA_LOG.Error("AssigningRole 校验操作账户是否拥有所有待分配的角色异常", zap.Any("userId", customerId), zap.Any("req", r), zap.Error(err))
		return ApiReturn.ErrSystem
	}
	requestRoleIds := strings.Split(r.RoleIds, ",")
	if len(roleIds) != len(requestRoleIds) {
		var roles []model.StockCasbinRoleModel
		ids := utils.SliceInterStr(roleIds, requestRoleIds)
		sql_role := `select * from stock_casbin_role where id in ( '` + strings.Join(ids, `,`) + `)`
		if err := global.GVA_DB.Raw(sql_role).Scan(&roles).Error; err != nil {
			global.GVA_LOG.Error("AssigningRole 查操作用户无权限分配的角色信息异常", zap.Any("NoPermissionRoleIds", ids), zap.Any("requestRoleIds", r.RoleIds))
			return ApiReturn.ErrSystem
		}
		msg := ""
		for i, role := range roles {
			if msg == "" {
				msg = "当前账户对角色：" + role.RoleName
			} else {
				msg += "," + role.RoleName
			}
			if i == len(roles)-1 {
				msg += "无权限"
			}
		}
		global.GVA_LOG.Error("AssigningRole 当前部分角色，暂无权限分配", zap.Any("roleIds", roleIds), zap.Any("NoPermissionRoleIds", roles), zap.Any("requestRoleIds", r.RoleIds))
		permission := ApiReturn.NoPermission
		permission.Msg = msg
		return permission
	}
	// 1.校验角色是否存在状态是否可用
	var roles []int
	var str = strings.Join(roleIds, `,`)
	sqls := `select id from stock_casbin_role where  status ='Y' And id in (` + str + `)`
	if err = global.GVA_DB.Raw(sqls).Scan(&roles).Error; err != nil {
		global.GVA_LOG.Error("AssigningRole 校验角色状态 异常", zap.Any("req", str), zap.Error(err))
		return ApiReturn.ErrSystem
	}
	if len(roles) != len(requestRoleIds) {
		global.GVA_LOG.Error("AssigningRole 有部分角色不可用/不存在", zap.Any("roleIds", roleIds), zap.Any("requestRoleIds", r.RoleIds))
		return ApiReturn.RoleSatatusNo
	}
	err = global.GVA_DB.Transaction(func(tx *gorm.DB) error {
		//校验通过 分配角色 参数指针类型 删除一条记录时，删除对象需要指定主键，否则会触发 批量 Delete，
		if e := tx.Where("user_id = ? ", r.UserId).Delete(&model.StockCasbinRoleRelationUserModel{}).Error; e != nil {
			global.GVA_LOG.Error("AssigningRole 删除所有用户角色关系 异常", zap.Any("req", str), zap.Error(e))
			return errors.New(ApiReturn.ErrSystem.Msg)
		}
		for _, v := range roles {
			now := model.LocalTime(time.Now())
			if e := tx.Model(model.StockCasbinRoleRelationUserModel{}).Create(&model.StockCasbinRoleRelationUserModel{
				RoleId:      v,
				UserId:      r.UserId,
				Status:      "Y",
				CreateTime:  &now,
				LastUpdTime: &now,
			}).Error; e != nil {
				global.GVA_LOG.Error("AssigningRole 建立用户和角色关系 异常", zap.Any("req", roles), zap.Error(e))
				return errors.New(ApiReturn.ErrSystem.Msg)
			}
		}
		return nil
	})
	if err != nil {
		return ApiReturn.ApiReturnCode{
			Code: ApiReturn.TxErrSystem.Code,
			Data: ApiReturn.TxErrSystem.Data,
			Msg:  err.Error(),
		}
	}
	return ApiReturn.OK
}

//GetStockCasbinRoleRelationUser 多条件查询
func (u *StockCasbinRoleRelationUserService) GetStockCasbinRoleRelationUser(req *model.StockCasbinRoleRelationUserModel) (a ApiReturn.ApiReturnCode) {
	var mo []model.StockCasbinRoleRelationUserModel
	sql := ""
	obj := model.NewStockCasbinRoleRelationUserModel()
	tableName := obj.TableName()
	sqlCondition := utils.ReflectHandleStuct(req)
	if sqlCondition != "" {
		sql = `select * from ` + tableName + ` where ` + sqlCondition
	} else {
		sql = `select * from ` + tableName + ` order by id desc  limit 100 `
	}
	err := global.GVA_DB.Raw(sql).Scan(&mo).Error
	if err != nil {
		global.GVA_LOG.Error("casbin Get异常", zap.Any("req", req), zap.Any("sql", sql), zap.Error(err))
		return ApiReturn.ErrSystem
	}
	s := ApiReturn.OK
	s.Data = mo
	return s
}

//InsertStockCasbinRoleRelationUser
func (u *StockCasbinRoleRelationUserService) InsertStockCasbinRoleRelationUser(req *model.StockCasbinRoleRelationUserModel) (a ApiReturn.ApiReturnCode) {
	err := global.GVA_DB.Model(req).Create(req).Error
	if err != nil {
		global.GVA_LOG.Error("casbin insert异常", zap.Any("req", req), zap.Error(err))
		return ApiReturn.ErrSystem
	}
	return ApiReturn.OK
}

//UpdateStockCasbinRoleRelationUser 更新
func (u *StockCasbinRoleRelationUserService) UpdateStockCasbinRoleRelationUser(req *model.StockCasbinRoleRelationUserModel) (a ApiReturn.ApiReturnCode) {
	if req.Id == 0 {
		return ApiReturn.ErrParam
	}
	err := global.GVA_DB.Model(req).Updates(req).Error
	if err != nil {
		global.GVA_LOG.Error("casbin Update异常", zap.Any("req", req), zap.Error(err))
		return ApiReturn.ErrSystem
	}
	return ApiReturn.OK
}

//DelStockCasbinRoleRelationUser 根据ID删除
func (u *StockCasbinRoleRelationUserService) DelStockCasbinRoleRelationUser(req *model.StockCasbinRoleRelationUserModel) (a ApiReturn.ApiReturnCode) {
	if req.Id == 0 {
		return ApiReturn.ErrParam
	}
	err := global.GVA_DB.Model(req).Where("id = ?", req.Id).Delete(model.StockCasbinRoleRelationUserModel{}).Error
	if err != nil {
		global.GVA_LOG.Error("casbin Del异常", zap.Any("req", req), zap.Error(err))
		return ApiReturn.ErrSystem
	}
	return ApiReturn.OK
}
